import { isObject } from "../help";

function genElement(node){
    if (node.tag && !node.key){
        // div
        return genTag(node);
    }else if (node.text){
        // 文本
        return `_v('${node.text.trim()}')`;
    }else if (node.value){
        // 模板
        return `_s(${node.value.trim()})`;
    }else if (node.key){
        // if 语法
        if (node.ifProcessed)return;
        return genIf(node);
    }
    
}
function normalizeData(attrs){
    const data = {
        staticClass: null,
        staticStyle: null,
        styleBinding: null,
        classBinding: null,
        props: {},
        attrs: {},
        on: {},
        attrsMap: {},
        directives: {}, // 指令
        ref: null,
        slot: null,
        slotScope: null
    };
    for(let i=0; i<attrs.length; i++){
        let {key, value, hasValue} = attrs[i];
        data.attrsMap[key] = value;
        if (key.startsWith(":")){
            key = key.slice(1);
            data.props[key] = value;
            continue
        }else if (key.startsWith("v-bind:")){
            key = key.slice(8);
            data.props[key] = value;
            continue
        }else if (key.startsWith("@")){
            key = key.slice(1);
            data.on[key] = value;
            continue
        }else if (key.startsWith("v-on:")){
            key = key.slice(5);
            data.on[key] = value;
            continue
        }else if (key === "class"){
            data.staticClass = value;
        }else if (key=== "style"){
            data.staticStyle = value;
        }else if (key.startsWith("v-")){
            key = key.slice(2);
            data.directives[key] = value;
        }else if (key==="ref"){
            data.ref = value;
        }else{
            // 普通dom属性
            data.attrs[key] = value;
        }
    }
    if (data.props.class){
        data.classBinding = data.props.class;
        delete data.props.class;
    }
    if (data.props.style){
        data.styleBinding = data.props.style;
        delete data.props.style;
    }
    if (data.attrs.slot){
        data.slot = data.attrs.slot;
    }
    if (data.attrs['slot-scope']){
        data['slotScope'] = data.attrs['slot-scope']
    }
    return data;
}
function genData(attrs){
    /*
    [  
        {key: 'class', hasValue: true, value: 'app'}
    ]
    */
    // 需要把这上面的抽取转换一下
    /*
    {
        on: 专门的事件
        attrs
    }
    */
    let code = '{';
    const noramlizedAttrs = normalizeData(attrs);
    // <div :class="a" class='b'>  class: {'a': a, 'b': true}
    if (noramlizedAttrs.staticClass){
        code += 'staticClass:\''+ noramlizedAttrs.staticClass + '\',';
    }
    if (noramlizedAttrs.classBinding){
        code += 'class:'+ noramlizedAttrs.classBinding + ',';
    }
    if (noramlizedAttrs.styleBinding){
        code += 'style:'+ noramlizedAttrs.styleBinding + ',';
    }
    if (noramlizedAttrs.staticStyle){
        code += 'staticStyle:\''+ noramlizedAttrs.staticStyle + '\',';
    }
    if (Object.keys(noramlizedAttrs.attrs).length){
        code += 'attrs: ' + genDomAttrs(noramlizedAttrs.attrs) + ',';
    }
    if (Object.keys(noramlizedAttrs.props).length){
        code += 'props:'+ genProps(noramlizedAttrs.props) + ',';
    }
    if (Object.keys(noramlizedAttrs.on).length){
        code += 'on:' + genEvent(noramlizedAttrs.on) + ',';
    }
    // console.log(noramlizedAttrs.directives)
    // debugger;
    // if (Object.keys(noramlizedAttrs.directives).length){
    //     code += 'directives:' + genEvent(noramlizedAttrs.directives) + ',';
    // }
    if (noramlizedAttrs.ref){
        code += `ref: '${noramlizedAttrs.ref}'`
    }
    // console.log(noramlizedAttrs);
    if (noramlizedAttrs.slot && !noramlizedAttrs.slotScope){
        code += `slot: '${noramlizedAttrs.slot}'`
    }
    // if (noramlizedAttrs.slotScope){
    //     const slotName = noramlizedAttrs.slot || 'default';
    //     code += `slotScope: ` +`_u([{key: '${slotName}', fn: function(){}}])`
    // }
    if (!noramlizedAttrs.slotScope || noramlizedAttrs.directives.length===0){
        // slotScope 需要子节点
        code = code.replace(/,$/, '')+'}';
    }
    return [code, noramlizedAttrs];
}
function genProps(props){
    let code = '{';
    const keys = Object.keys(props);
    for (let key of keys){
        const value = props[key];
        code += `'${key}': ${value},`;
    }
    return code.replace(/,$/, '')+'}';
}
function genDomAttrs(domAttrs){
    let code = '{';
    const keys = Object.keys(domAttrs);
    for (let key of keys){
        const domValue = domAttrs[key];
        code += `'${key}': '${domValue}',`;
    }
    return code.replace(/,$/, '')+'}';
}
function genEvent(events){
    let code = '{';
    /*
    <div class="app" @click="count++">
        <child :aaa="count" @add="addFn"/>
    </div>
    {
        on: function($event){count++}
    }
    {
        on: addFn
    }
    */
    const keys = Object.keys(events);
    for (let key of keys){
        const userDef = events[key];
        if (/^\w+$/.test(userDef)){
            code += `'${key}': ${userDef},`;
        }else{
            code += `'${key}': function($event){${userDef}},`;
        }
    }
    return code.replace(/,$/, '')+'}';
}
function flatJsonClass(classBinding){
    let code = '';
    if (Array.isArray(data)){
        data.forEach(item=>{
            flatJsonClass(item);
        });
    }else if (isObject(classBinding)){
        
    }
}
function normalizeClassBinding(classBinding){
    // "a", "[a, b]", "[a, {b: true}]"
   let code = '';
   if (/^\w+$/.test(classBinding)){
    // "a"
    code += `'${a}': true,`;
   }else{
    const data = JSON.parse(classBinding);
    code += flatJsonClass(data);
   }
}
function genClass(staticClass, classBinding){
    /*
    {
        staticClass: "",
        class: ""
    }
    */
    let code = '{';
    staticClass.split(" ").forEach((className)=>{
        className = className.trim();
        if (className){
            code += `'${className}': true,`
        }
    });

    return code.replace(/,$/, '')+'}';
    // normalizeClassBinding(classBinding);
}
function genIf(node){
    node.ifProcessed = true;
    const {alternate, key, condition, block} = node;
    if (key === 'v-else'){
        return ` ${genElement(block)}`
    }
    let code = `${condition} ? ${genElement(block)}:`;
    // if (alternate.length === 0){
    //     code += '_e()';
    //     return code;
    // }
    for (let i=0; i<alternate.length; i++){
        code += genIf(alternate[i]);
    }
    if (alternate[alternate.length-1]?.key === 'v-else-if'){
        code += '_e()'
    }
    if (alternate.length===0){
        code += '_e()'
    }
    return code;

}
function _genDirective(directives){
    let code = `[`;
    for (let name in directives){
        code += `{name: '${name}', directive: '${directives[name]}', expression: ${directives[name]}},`
    }
    code = code.replace(/\,$/g, '');
    return code += ']';
}
function genDirective(directives){
    // 其他的传到render里面, 渲染时候需要用到这些数据
    return _genDirective(directives);

}
function genTag(node){
    let [data, noramlizedAttrs] = genData(node.attrs);
    // <slot :aaa="aaa"></slot>
    if (node.tag === 'slot'){
        const name = noramlizedAttrs.attrsMap.name || 'default';
        delete noramlizedAttrs.attrsMap.name 
        return `_t('${name}', ${genProps(noramlizedAttrs.props)})`;
    }
    // 指令需要特殊处理
    const children = node.children;
    const childrenNodes = children.map(child=>genElement(child));
    if (noramlizedAttrs.slotScope){
        const slotName = noramlizedAttrs.slot || 'default';
        const var1 = noramlizedAttrs.slotScope;
        data += `slotScope: ` +`_u([{key: '${slotName}', fn: function(${var1}){return [${childrenNodes}]}}])}`;
        return `_c('${node.tag}', ${data}, [])`;
    }else if (noramlizedAttrs.directives.for){
        // item in items
        let code = `_c('${node.tag}', ${data}, [${childrenNodes}])`;
        const binding = noramlizedAttrs.directives.for.split(' ');
        const var1 = binding[0].trim();
        const var2 = binding[2].trim();
        code = `_l(${var2}, function(${var1}){return ${code}})`
        delete noramlizedAttrs.directives.for;
        return code;
    }else{
        let directives =  genDirective(noramlizedAttrs.directives, node);
        if (Object.keys(noramlizedAttrs.directives).length>0){
            data = data.replace(/\}/g, '');
            data += 'directives:'+directives;
            data += '}'

        }
        let code = `_c('${node.tag}', ${data}, [${childrenNodes}])`;
        return code;
    }
    
    
}

export function genRender(ast){
    const code = genElement(ast);
    return code;
}
